#include<iostream>

template <class T>//由于引用折叠的限制,f1与任何引用实例化后都是一个左值引用
void f1(T& x)
{}

template <class T>//由于引用折叠限定,f2实例化后可以是左值引用,也可以是右值引用,我们称这种引用是万能引用
void f2(T&& x)
{}
int main()
{
    // int n = 0;
    // //int& &&r = n;//直接写多重引用不符合语法规则会报错,但是可以通过typedef和using操作构成引用的引用折叠

    // typedef int& lref;
    // using rref = int&&;

    // lref& r1 = n;//r1的类型是int&
    // lref&& r2 = n;//r2的类型是int&
    // rref& r3 = n;//r3的类型是int&
    // rref&& r4 = 0;//r4的类型是int&&
    // //只有右值引用和右值引用会构成右值引用,其余的全部都是左值引用

    //无折叠->实例化为void f1(int& x)
    int n = 0;
    f1<int> (n);
    //f1<int> (0);//报错

    //int &->实例化为void f1(int& x)
    f1<int&>(n);
    //f1<int&>(0);//报错

    //int &&->实例化为void f1(int& x)
    f1<int&&>(n);
    //f1<int&&>(0);//报错

    //const int &->实例化为void f1(const int& x)
    f1<const int&>(n);
    f1<const int&>(0);//const int& 可以引用右值

    //const int &&->实例化为 void f1(const int& x)
    f1<const int&&>(n);
    f1<const int&&>(0);//const int& 可以引用右值

    //无折叠->实例化为void f2(int&& x)
    //f2<int>(n);//右值引用无法引用左值
    f2<int>(0);

    //int &->实例化为void f2(int& x)
    f2<int&>(n);
    //f2<int&>(0);//左值引用不能引用右值

    //int &&->实例化为void f2(int&& x)
    //f2<int&&>(n);//右值引用不能引用左值
    f2<int&&>(0);

    return 0;
}


//万能引用应用场景

// template<class T>
// void Function(T&& t)
// {
//     int a = 0;
//     T x = a;
//     //x++;
//     std::cout << &a << std::endl;
//     std::cout << &x << std::endl << std::endl; 
// }

// int main()
// {
//     //实例化为void Function(T&& t)可以运行通过右值引用引用右值,a和x的地址不一样
//     Function(10);

//     int a;
//     //a是左值,实例化为void Function(T& t),a和x的值一样
//     Function(a);

//     //实例化为void Function(T&& t)可以运行通过右值引用引用右值,a和x的地址不一样
//     Function(std::move(a));

//      const int b = 8;
//     //b是const左值,实例化为void Function(const T& t),a和x的值一样,x不可以修改
//     Function(b);

//     //实例化为void Function(const T&& t)可以运行通过右值引用引用右值,a和x的地址不一样,x不可以修改
//     Function(std::move(b));
//     return 0;
// }